home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / plotting / gnuplot3.lzh / gnuplot / parse.c < prev    next >
C/C++ Source or Header  |  1991-09-06  |  10KB  |  562 lines

  1. /* GNUPLOT - parse.c */
  2. /*
  3.  * Copyright (C) 1986, 1987, 1990, 1991   Thomas Williams, Colin Kelley
  4.  *
  5.  * Permission to use, copy, and distribute this software and its
  6.  * documentation for any purpose with or without fee is hereby granted, 
  7.  * provided that the above copyright notice appear in all copies and 
  8.  * that both that copyright notice and this permission notice appear 
  9.  * in supporting documentation.
  10.  *
  11.  * Permission to modify the software is granted, but not the right to
  12.  * distribute the modified code.  Modifications are to be distributed 
  13.  * as patches to released version.
  14.  *  
  15.  * This software is provided "as is" without express or implied warranty.
  16.  * 
  17.  *
  18.  * AUTHORS
  19.  * 
  20.  *   Original Software:
  21.  *     Thomas Williams,  Colin Kelley.
  22.  * 
  23.  *   Gnuplot 2.0 additions:
  24.  *       Russell Lang, Dave Kotz, John Campbell.
  25.  *
  26.  *   Gnuplot 3.0 additions:
  27.  *       Gershon Elber and many others.
  28.  * 
  29.  * Send your comments or suggestions to 
  30.  *  pixar!info-gnuplot@sun.com.
  31.  * This is a mailing list; to join it send a note to 
  32.  *  pixar!info-gnuplot-request@sun.com.  
  33.  * Send bug reports to
  34.  *  pixar!bug-gnuplot@sun.com.
  35.  */
  36.  
  37. #include <stdio.h>
  38. #include <setjmp.h>
  39. #include <signal.h>
  40. #include <errno.h>
  41. #include <math.h>
  42. #include "plot.h"
  43.  
  44. #ifndef vms
  45. #ifndef __ZTC__
  46. extern int errno;
  47. #endif
  48. #endif
  49.  
  50. extern int num_tokens,c_token;
  51. extern struct lexical_unit token[];
  52. extern char c_dummy_var[MAX_NUM_VAR][MAX_ID_LEN+1];    /* name of current dummy vars */
  53. extern struct udft_entry *dummy_func;    /* pointer to dummy variable's func */
  54.  
  55. struct value *pop(),*integer(),*complex();
  56. struct at_type *temp_at(), *perm_at();
  57. struct udft_entry *add_udf();
  58. struct udvt_entry *add_udv();
  59. union argument *add_action();
  60.  
  61. struct at_type at;
  62. static jmp_buf fpe_env;
  63.  
  64. #define dummy (struct value *) 0
  65.  
  66. #ifdef __TURBOC__
  67. void fpe()
  68. #else
  69. #ifdef __ZTC__
  70. void fpe(an_int)
  71. int an_int;
  72. #else
  73. #ifdef _CRAY
  74. void fpe(an_int)
  75. int an_int;
  76. #else
  77. fpe()
  78. #endif
  79. #endif
  80. #endif
  81. {
  82. #ifdef PC    /* thanks to lotto@wjh12.UUCP for telling us about this  */
  83.     _fpreset();
  84. #endif
  85.     (void) signal(SIGFPE, fpe);
  86.     undefined = TRUE;
  87.     longjmp(fpe_env, TRUE);
  88. }
  89.  
  90.  
  91. #ifdef apollo
  92. #include <apollo/base.h>
  93. #include <apollo/pfm.h>
  94. #include <apollo/fault.h>
  95.  
  96. /*
  97.   On an Apollo, the OS can signal a couple errors that are not mapped
  98.   into SIGFPE, namely signalling NaN and branch on an unordered
  99.   comparison.  I suppose there are others, but none of these are documented,
  100.   so I handle them as they arise.
  101.  
  102.   Anyway, we need to catch these faults and signal SIGFPE.
  103. */
  104.  
  105. pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t& fault_rec)
  106. {
  107.     kill(getpid(), SIGFPE);
  108.     return pfm_$continue_fault_handling;
  109. }
  110.  
  111. apollo_pfm_catch()
  112. {
  113.     status_$t status;
  114.     pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop,
  115.                  apollo_sigfpe, &status);
  116.     pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop,
  117.                  apollo_sigfpe, &status);
  118. }
  119. #endif
  120.  
  121.  
  122. evaluate_at(at_ptr,val_ptr)
  123. struct at_type *at_ptr;
  124. struct value *val_ptr;
  125. {
  126.     double temp, real();
  127.  
  128.     undefined = FALSE;
  129.     errno = 0;
  130.     reset_stack();
  131.     if (setjmp(fpe_env))
  132.         return;                /* just bail out */
  133.     (void) signal(SIGFPE, fpe);    /* catch core dumps on FPEs */
  134.  
  135.     execute_at(at_ptr);
  136.  
  137.     (void) signal(SIGFPE, SIG_DFL);
  138.  
  139.     if (errno == EDOM || errno == ERANGE) {
  140.         undefined = TRUE;
  141.     } else {
  142.         (void) pop(val_ptr);
  143.         check_stack();
  144.     }
  145. /* At least one machine (ATT 3b1) computes Inf without a SIGFPE */
  146.     temp = real(val_ptr);
  147.     if (temp > VERYLARGE || temp < -VERYLARGE) {
  148.         undefined = TRUE;
  149.     }
  150. }
  151.  
  152.  
  153. struct value *
  154. const_express(valptr)
  155. struct value *valptr;
  156. {
  157. register int tkn = c_token;
  158.     if (END_OF_COMMAND)
  159.         int_error("constant expression required",c_token);
  160.     evaluate_at(temp_at(),valptr);    /* run it and send answer back */
  161.     if (undefined) {
  162.         int_error("undefined value",tkn);
  163.     }
  164.     return(valptr);
  165. }
  166.  
  167.  
  168. struct at_type *
  169. temp_at()    /* build a static action table and return its pointer */
  170. {
  171.     at.a_count = 0;        /* reset action table !!! */
  172.     express();
  173.     return(&at);
  174. }
  175.  
  176.  
  177. /* build an action table, put it in dynamic memory, and return its pointer */
  178.  
  179. struct at_type *
  180. perm_at()
  181. {
  182. register struct at_type *at_ptr;
  183. register unsigned int len;
  184.  
  185.     (void) temp_at();
  186.     len = sizeof(struct at_type) -
  187.         (MAX_AT_LEN - at.a_count)*sizeof(struct at_entry);
  188.     at_ptr = (struct at_type *) alloc(len, "action table");
  189.      (void) memcpy(at_ptr,&at,len);
  190.     return(at_ptr);
  191. }
  192.  
  193.  
  194. #ifdef NOCOPY
  195. /*
  196.  * cheap and slow version of memcpy() in case you don't have one
  197.  */
  198. memcpy(dest,src,len)
  199. char *dest,*src;
  200. unsigned int len;
  201. {
  202.     while (len--)
  203.         *dest++ = *src++;
  204. }
  205. #endif /* NOCOPY */
  206.  
  207.  
  208. express()  /* full expressions */
  209. {
  210.     xterm();
  211.     xterms();
  212. }
  213.  
  214. xterm()  /* ? : expressions */
  215. {
  216.     aterm();
  217.     aterms();
  218. }
  219.  
  220.  
  221. aterm()
  222. {
  223.     bterm();
  224.     bterms();
  225. }
  226.  
  227.  
  228. bterm()
  229. {
  230.     cterm();
  231.     cterms();
  232. }
  233.  
  234.  
  235. cterm()
  236. {
  237.     dterm();
  238.     dterms();
  239. }
  240.  
  241.  
  242. dterm()
  243. {    
  244.     eterm();
  245.     eterms();
  246. }
  247.  
  248.  
  249. eterm()
  250. {
  251.     fterm();
  252.     fterms();
  253. }
  254.  
  255.  
  256. fterm()
  257. {
  258.     gterm();
  259.     gterms();
  260. }
  261.  
  262.  
  263. gterm()
  264. {
  265.     hterm();
  266.     hterms();
  267. }
  268.  
  269.  
  270. hterm()
  271. {
  272.     unary(); /* - things */
  273.     iterms(); /* * / % */
  274. }
  275.  
  276.  
  277. factor()
  278. {
  279. register int value;
  280.  
  281.     if (equals(c_token,"(")) {
  282.         c_token++;
  283.         express();
  284.         if (!equals(c_token,")"))
  285.             int_error("')' expected",c_token);
  286.         c_token++;
  287.     }
  288.     else if (isnumber(c_token)) {
  289.         convert(&(add_action(PUSHC)->v_arg),c_token);
  290.         c_token++;
  291.     }
  292.     else if (isletter(c_token)) {
  293.         if ((c_token+1 < num_tokens)  && equals(c_token+1,"(")) {
  294.             value = standard(c_token);
  295.             if (value) {    /* it's a standard function */
  296.                 c_token += 2;
  297.                 express();
  298.                 if (!equals(c_token,")"))
  299.                     int_error("')' expected",c_token);
  300.                 c_token++;
  301.                 (void) add_action(value);
  302.             }
  303.             else {
  304.                 int call_type = (int )CALL;
  305.                 value = c_token;
  306.                 c_token += 2;
  307.                 express();
  308.                 if (equals(c_token, ",")) {
  309.                     c_token += 1;
  310.                     express();
  311.                     call_type = (int )CALL2;
  312.                 }
  313.                 if (!equals(c_token,")"))
  314.                     int_error("')' expected",c_token);
  315.                 c_token++;
  316.                 add_action(call_type)->udf_arg = add_udf(value);
  317.             }
  318.         }
  319.         else {
  320.             if (equals(c_token,c_dummy_var[0])) {
  321.                 c_token++;
  322.                 add_action(PUSHD1)->udf_arg = dummy_func;
  323.             }
  324.             else if (equals(c_token,c_dummy_var[1])) {
  325.                 c_token++;
  326.                 add_action(PUSHD2)->udf_arg = dummy_func;
  327.             }
  328.             else {
  329.                 add_action(PUSH)->udv_arg = add_udv(c_token);
  330.                 c_token++;
  331.             }
  332.         }
  333.     } /* end if letter */
  334.     else
  335.         int_error("invalid expression ",c_token);
  336.  
  337.     /* add action code for ! (factorial) operator */
  338.     while (equals(c_token,"!")) {
  339.         c_token++;
  340.         (void) add_action(FACTORIAL);
  341.     }
  342.     /* add action code for ** operator */
  343.     if (equals(c_token,"**")) {
  344.             c_token++;
  345.             unary();
  346.             (void) add_action(POWER);
  347.     }
  348.  
  349. }
  350.  
  351.  
  352.  
  353. xterms()
  354. {  /* create action code for ? : expressions */
  355.  
  356.     if (equals(c_token,"?")) {
  357.         register int savepc1, savepc2;
  358.         register union argument *argptr1,*argptr2;
  359.         c_token++;
  360.         savepc1 = at.a_count;
  361.         argptr1 = add_action(JTERN);
  362.         express();
  363.         if (!equals(c_token,":"))
  364.             int_error("expecting ':'",c_token);
  365.         c_token++;
  366.         savepc2 = at.a_count;
  367.         argptr2 = add_action(JUMP);
  368.         argptr1->j_arg = at.a_count - savepc1;
  369.         express();
  370.         argptr2->j_arg = at.a_count - savepc2;
  371.     }
  372. }
  373.  
  374.  
  375. aterms()
  376. {  /* create action codes for || operator */
  377.  
  378.     while (equals(c_token,"||")) {
  379.         register int savepc;
  380.         register union argument *argptr;
  381.         c_token++;
  382.         savepc = at.a_count;
  383.         argptr = add_action(JUMPNZ);    /* short-circuit if already TRUE */
  384.         aterm();
  385.         argptr->j_arg = at.a_count - savepc;/* offset for jump */
  386. #if defined(AMIGA_LC_5_1) || defined(AMIGA_AC_5)
  387.         (void) add_action(ABOOL);
  388. #else
  389.         (void) add_action(BOOL);
  390. #endif
  391.     }
  392. }
  393.  
  394.  
  395. bterms()
  396. { /* create action code for && operator */
  397.  
  398.     while (equals(c_token,"&&")) {
  399.         register int savepc;
  400.         register union argument *argptr;
  401.         c_token++;
  402.         savepc = at.a_count;
  403.         argptr = add_action(JUMPZ);    /* short-circuit if already FALSE */
  404.         bterm();
  405.         argptr->j_arg = at.a_count - savepc;/* offset for jump */
  406. #if defined(AMIGA_LC_5_1) || defined(AMIGA_AC_5)
  407.         (void) add_action(ABOOL);
  408. #else
  409.         (void) add_action(BOOL);
  410. #endif
  411.     }
  412. }
  413.  
  414.  
  415. cterms()
  416. { /* create action code for | operator */
  417.  
  418.     while (equals(c_token,"|")) {
  419.         c_token++;
  420.         cterm();
  421.         (void) add_action(BOR);
  422.     }
  423. }
  424.  
  425.  
  426. dterms()
  427. { /* create action code for ^ operator */
  428.  
  429.     while (equals(c_token,"^")) {
  430.         c_token++;
  431.         dterm();
  432.         (void) add_action(XOR);
  433.     }
  434. }
  435.  
  436.  
  437. eterms()
  438. { /* create action code for & operator */
  439.  
  440.     while (equals(c_token,"&")) {
  441.         c_token++;
  442.         eterm();
  443.         (void) add_action(BAND);
  444.     }
  445. }
  446.  
  447.  
  448. fterms()
  449. { /* create action codes for == and != operators */
  450.  
  451.     while (TRUE) {
  452.         if (equals(c_token,"==")) {
  453.             c_token++;
  454.             fterm();
  455.             (void) add_action(EQ);
  456.         }
  457.         else if (equals(c_token,"!=")) {
  458.             c_token++;
  459.             fterm();
  460.             (void) add_action(NE);
  461.         }
  462.         else break;
  463.     }
  464. }
  465.  
  466.  
  467. gterms()
  468. { /* create action code for < > >= or <= operators */
  469.     
  470.     while (TRUE) {
  471.         /* I hate "else if" statements */
  472.         if (equals(c_token,">")) {
  473.             c_token++;
  474.             gterm();
  475.             (void) add_action(GT);
  476.         }
  477.         else if (equals(c_token,"<")) {
  478.             c_token++;
  479.             gterm();
  480.             (void) add_action(LT);
  481.         }        
  482.         else if (equals(c_token,">=")) {
  483.             c_token++;
  484.             gterm();
  485.             (void) add_action(GE);
  486.         }
  487.         else if (equals(c_token,"<=")) {
  488.             c_token++;
  489.             gterm();
  490.             (void) add_action(LE);
  491.         }
  492.         else break;
  493.     }
  494.  
  495. }
  496.  
  497.  
  498.  
  499. hterms()
  500. { /* create action codes for + and - operators */
  501.  
  502.     while (TRUE) {
  503.             if (equals(c_token,"+")) {
  504.                 c_token++;
  505.                 hterm();
  506.                 (void) add_action(PLUS);
  507.             }
  508.             else if (equals(c_token,"-")) {
  509.                 c_token++;
  510.                 hterm();
  511.                 (void) add_action(MINUS);
  512.             }
  513.             else break;
  514.     }
  515. }
  516.  
  517.  
  518. iterms()
  519. { /* add action code for * / and % operators */
  520.  
  521.     while (TRUE) {
  522.             if (equals(c_token,"*")) {
  523.                 c_token++;
  524.                 unary();
  525.                 (void) add_action(MULT);
  526.             }
  527.             else if (equals(c_token,"/")) {
  528.                 c_token++;
  529.                 unary();
  530.                 (void) add_action(DIV);
  531.             }
  532.             else if (equals(c_token,"%")) {
  533.                 c_token++;
  534.                 unary();
  535.                 (void) add_action(MOD);
  536.             }
  537.             else break;
  538.     }
  539. }
  540.  
  541.  
  542. unary()
  543. { /* add code for unary operators */
  544.     if (equals(c_token,"!")) {
  545.         c_token++;
  546.         unary();
  547.         (void) add_action(LNOT);
  548.     }
  549.     else if (equals(c_token,"~")) {
  550.         c_token++;
  551.         unary();
  552.         (void) add_action(BNOT);
  553.     }
  554.     else if (equals(c_token,"-")) {
  555.         c_token++;
  556.         unary();
  557.         (void) add_action(UMINUS);
  558.     }
  559.     else
  560.         factor();
  561. }
  562.